package thread;

import java.util.concurrent.atomic.AtomicInteger;

/**
 * @User: vitobo
 * @Date: 2024-08-06
 * @Description: CAS的应用场景: 使用原子类, 解决线程安全问题;
 *
 *  synchronized 属于"通用方法", 适合各种场景, 都能使用
 *  CAS 属于 "特殊方法", 只是特定场景能使用, 没那么通用;
 */


/*
// 实现自旋锁
public class SpinLock {
    // 当前的锁 是谁加的;
    private Thread owner = null;
    public void lock(){
        // 通过 CAS 看当前锁是否被某个线程持有.
        // 如果这个锁已经被别的线程持有, 那么就自旋等待.
        // 如果这个锁没有被别的线程持有, 那么就把 owner 设为当前尝试加锁的线程.

        // 检测当前的owner是否为null, 如果是null, 就进行交换, 也就是把当前的引用赋值给owner.
        // 如果赋值成功, 此时循环结束, 加锁完成了;

        // 如果当前 锁, 已经被别的线程占用了, CAS就会发现 this.owner 不是 null;
        // CAS就不会产生赋值, 也同时返回false, 循环继续执行,并进行下次判定;

        // 这里的CAS, 是一个伪代码;
        while(!CAS(this.owner, null, Thread.currentThread())){}
        public void unlock(){
            this.owner = null;
        }
    }
}
 */

public class ThreadDemo28 {
    public static void main(String[] args) throws InterruptedException {
        // 这些原子类, 就是基于 CAS 实现了 自增, 自减等操作. 此时进行这类操作不需要加锁, 也是线程安全的.
        AtomicInteger count = new AtomicInteger(0);

        // 使用原子类, 来解决线程安全问题.
        Thread t1 = new Thread(() -> {
            for (int i = 0; i < 50000; i++) {
                // 因为 java 不支持运算符重载, 所以只能使用普通方法来表示自增自减.
                count.getAndIncrement(); // count++
                // count.incrementAndGet(); // ++count
                // count.getAndDecrement(); // count--
                // count.decrementAndGet(); // --count
            }
        });
        Thread t2 = new Thread(() -> {
            for (int i = 0; i < 50000; i++) {
                count.getAndIncrement();
            }
        });
        t1.start();
        t2.start();
        t1.join();
        t2.join();

        System.out.println(count.get());
    }
}
